package cn.libinal.scloud.base.common.service.impl;

import cn.libinal.scloud.base.common.entity.JpaBaseEntity;
import cn.libinal.scloud.base.common.repository.BaseJpaRepository;
import cn.libinal.scloud.base.common.service.BaseJpaService;
import cn.libinal.scloud.base.common.web.DataPageRequest;
import com.querydsl.core.types.Predicate;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.Page;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.util.Optional;

/**
 * 自定义业务类
 * @author libinal
 * @param <T> 实体类型
 * @param <R> JPA接口
 */
public abstract class AbstractJpaServiceImpl<T extends JpaBaseEntity, R extends BaseJpaRepository<T, String>> implements BaseJpaService<T> {

    protected R repository;

    public AbstractJpaServiceImpl(R repository) {
        this.repository = repository;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public T create(T source) {
        Assert.isNull(source.getId(), "新增时Id必须为空");
        return repository.save(source);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public T update(T source) {
        Assert.notNull(source.getId(), "更新时Id不能为空");
        Optional<T> optional = repository.findById(source.getId());
        if (optional.isPresent()) {
            T target = optional.get();
            BeanUtils.copyProperties(source, target, JpaBaseEntity.getNullProperties(source));
            return repository.save(target);
        }
        return null;
    }

    @Override
    public T findById(String id) {
        Assert.notNull(id, "查询时Id不能为空");
        return repository.findById(id).orElse(null);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void delete(String id) {
        Assert.notNull(id, "删除时Id不能为空");
    }

    @Override
    public Page<T> findByPaging(T source, DataPageRequest pageRequest) {
        return repository.findAll(buildPagingPredicates(source), pageRequest.buildPageRequest());
    }

    /**
     * 构建分页查询条件
     *
     * @param t 查询参数
     * @return Predicate查询条件
     */
    public abstract Predicate buildPagingPredicates(T t);

    @Override
    public Page<T> findByPaging(Predicate predicate, DataPageRequest pageRequest) {
        return repository.findAll(predicate, pageRequest.buildPageRequest());
    }
}
